﻿using System;
using TSU.FAMC.ComputerEngineering.Classes.Circuits.Events;
using TSU.FAMC.ComputerEngineering.Classes.Enums;

namespace TSU.FAMC.ComputerEngineering.Classes.Circuits.Basis
{
    /// <summary>
    /// Constant 1 gate element with one output and one input.
    /// </summary>
    public class Constant1Gate : Gate
    {
        // Methods

        /// <summary>
        /// Default construcotor.
        /// </summary>
        public Constant1Gate()
        {
            // contraining input and output interface
            Inputs.OnModified += Inputs_OnModified;
            Outputs.OnModified += Outputs_OnModified;
        }

        /// <summary>
        /// Resets CONSTANT1 gate.
        /// </summary>
        public override void Reset()
        {
            base.Reset();

            // transmitting 1 signal
            var signal = new Signal {Value = BooleanValue.True};
            AcceptSignal(signal);
        }

        /// <summary>
        /// Processes inputs signals and produces a result signal.
        /// </summary>
        /// <returns>Resulting signal. If Value of the signal is BooleanValue.UNDEFINED it means processing failed.</returns>
        public override Signal Process()
        {
            if (InputSignals.Count == 0)
            {
                var result = new Signal {Value = BooleanValue.Undefined};
                return result;
            }

            // always returning true signal
            return new Signal { Value = BooleanValue.True };
        }


        // Event handlers

        /// <summary>
        /// OnModified event handler for input interface.
        /// </summary>
        /// <param name="sender">Sender object.</param>
        /// <param name="e">Event arguments.</param>
        private void Outputs_OnModified(object sender, CircuitInterfaceEventArgs e)
        {
            if (Outputs.Count > 1)
            {
                throw new InvalidOperationException("Constant1 element has to have only one output. Use Joint element for n-m relation.");
            }
        }

        /// <summary>
        /// OnModified event handler for output interface.
        /// </summary>
        /// <param name="sender">Sender object.</param>
        /// <param name="e">Event arguments.</param>
        private void Inputs_OnModified(object sender, CircuitInterfaceEventArgs e)
        {
            if (Inputs.Count > 1)
            {
                throw new InvalidOperationException("Constant1 element has to have only one input. Use Joint element for n-m relation.");
            }
        }

        /// <summary>
        /// Clones constant1 element.
        /// </summary>
        /// <returns>Cloned constant1 element.</returns>
        public override object Clone()
        {
            return new Constant1Gate
            {
                Delay = Delay,
                Id = Id,
                Name = Name
            };
        }
    }
}
